﻿#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
using Zombie_Demo.Utilities;
using Zombie_Demo.User_Interface;
#endregion

namespace Zombie_Demo
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        World.Player player;
        static World.Camera camera;
        Vector2 distance;
        float rotation;
        private static Utilities.Scripting.Lua_Virtual_Machine luaVM;
        Frame f;
        Frame menu;

        private World.NPC.NPC npc;

        public static World.Camera Cam
        {
             get { return camera; }
        }

        internal static Utilities.Scripting.Lua_Virtual_Machine Lua
        {
            get { return luaVM; }
        }

        public Game1()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
             this.IsMouseVisible = true;
            ContentLibrary.SetContent(Content);
            Utilities.Event_System.EventManager.Init();
            luaVM = new Utilities.Scripting.Lua_Virtual_Machine();

            luaVM.AddMethodToLua("DebugPrint", this, this.GetType().GetMethod("DebugPrint"));
            luaVM.AddMethodToLua("ExitGame", this, this.GetType().GetMethod("ExitGame"));
            //Server.ClientConnect.Init();

            player = new World.Player();
            camera = new World.Camera(GraphicsDevice);
            KeyboardWrapper.Init();
            MouseWrapper.Init(camera);


             f = new Frame(new Vector2(0, 0));
            f.Bounds = camera.BoundingBox;
            //BackgroundRectangle b1 = new BackgroundRectangle(new Vector2(0, 0), 100, 30, Color.Black, f);
            //f.AddElement(b1);
            //BackgroundRectangle b2 = new BackgroundRectangle(new Vector2(10, 10), 50, 15, Color.White, f);
            //f.AddElement(b2);
            //Text t1 = new Text("Hello", Color.Black, "PL14", b2);
            //b2.AddElement(t1);

            

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            ContentLibrary.Init(this);
            World.PageSystem.Init();

            player.Load();
            ContentLibrary.LoadFont("PL14", "Palatino_Linotype_14");

            //User_Interface.XML_Handler.Serialize<Frame>(f, "Content\\XML\\test");
            //f = User_Interface.XML_Handler.DeSerialize<Frame>("test");

            //menu = new Frame(f, "MainMenu", new Rectangle(0, 0, 150, 200));
            //menu.Anchor = Element.AnchorPosition.CENTER;
            //menu.Hidden = true;
            //BackgroundRectangle bgMenu = new BackgroundRectangle(menu.Bounds, Color.Gray, menu);
            //Button exitButton = new Button("Exit Game", new Vector2(0, -35), menu, "ExitGameButton");
            //exitButton.Anchor = Element.AnchorPosition.LOWERCENTER;
            //exitButton.SetCommand("ExitGame()");

            //User_Interface.XML_Handler.Serialize<Frame>(menu, "Content\\XML\\MainMenu");

            menu = User_Interface.XML_Handler.DeSerialize<Frame>("MainMenu");
            f.AddElement(menu);

            npc = new World.NPC.NPC(new Vector2(300, 300), new Vector2(100, 100), true, 100, "TopDownZombie");
            f.Load();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            Content.Unload();
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (KeyboardWrapper.GetKeyState(Keys.Escape).FirstPress())
            {
                menu.Hidden = !menu.Hidden;
            }

            MouseWrapper.Update(camera);
            KeyboardWrapper.Update();

            PlayerRotation();
            player.Update();
            camera.Update(player.Position, this.GraphicsDevice);

            World.PageSystem.Update(new Point((int)player.Position.X, (int)player.Position.Y));

            npc.Update(gameTime);

            f.Update(gameTime);

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            //Drawing for the world
            spriteBatch.Begin(SpriteSortMode.Immediate,
                BlendState.AlphaBlend,
                null,
                null,
                null,
                null,
                camera.getTransform(GraphicsDevice));

            World.PageSystem.Draw(spriteBatch, camera.BoundingBox);
            player.Draw(spriteBatch, rotation);

            npc.Draw(gameTime, spriteBatch);

            spriteBatch.End();

            //Drawing for the UI
            spriteBatch.Begin();
            f.Draw(gameTime, spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }

        private void PlayerRotation()
        {
            MouseState mouse = Mouse.GetState();

            distance.X = Utilities.MouseWrapper.GetWorldCordinates(camera).X - player.Position.X;
            distance.Y = Utilities.MouseWrapper.GetWorldCordinates(camera).Y - player.Position.Y;

            rotation = (float)Math.Atan2(distance.Y, distance.X);
        }

        public void DebugPrint(string s)
        {
            Console.WriteLine(s);
        }

        public void ExitGame()
        {
            Utilities.ErrorManager.PrintAllErrors();
            Utilities.Log.WriteLog();
            Comm.Client.Disconnect();
            Exit();
        }
    }
}
